package com.atguigu.tingshu.album.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.config.MinioConstantProperties;
import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest;
import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse;
import com.tencentcloudapi.vod.v20180717.models.MediaInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private MinioConstantProperties minioConstantProperties;
    @Autowired
    private VodConstantProperties vodConstantProperties;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoService albumInfoService;

    @Autowired
    private VodService vodService;

    @Override
    public IPage<Map<String, Object>> findAlbumTrackPage(Page<Map<String, Object>> mapWithPage, Long albumId) {
        return trackInfoMapper.findAlbumTrackPage(mapWithPage, albumId);
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListWithPage, TrackInfoQuery trackInfoQuery) {

        return trackInfoMapper.findUserTrackPage(trackListWithPage, trackInfoQuery);
    }

    @Override
    public JSONObject uploadTrack(MultipartFile file) {
//        //上传
//		MinioClient minioClient = MinioClient.builder()
//				.endpoint(minioConstantProperties.getEndpointUrl())
//				.credentials(minioConstantProperties.getAccessKey(), minioConstantProperties.getSecreKey())
//				.build();
//
//		//开始上传mp4格式的文件，并获得媒体在线地址
//
//		//生成一个UUID防止重复上传后失效
//		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
//		//获取文件后缀并拼接uuid
//		String filename =  uuid + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
//
//        try {
//			PutObjectArgs putObjectArgs = PutObjectArgs.builder()
//					.bucket(minioConstantProperties.getBucketName())
//					.object(filename)
//					.stream(file.getInputStream(), file.getSize(), -1)
//					.contentType(file.getContentType())
//					.build();
//
//			minioClient.putObject(putObjectArgs);
//        } catch (Exception e) {
//           e.printStackTrace();
//        }
//
//       String url = minioConstantProperties.getEndpointUrl() + "/" + minioConstantProperties.getBucketName() + "/"  +filename;
//
//        JSONObject result = new JSONObject();
//		//返回JSONObject{mediaField=?,mediaUrl = ? }
//		result.put("mediaUrl",url);
//		return  result ;
        //
        VodUploadClient client = new VodUploadClient(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());


        VodUploadRequest request = new VodUploadRequest();

        String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
        request.setMediaFilePath(tempPath);

        try {
            VodUploadResponse response = client.upload(vodConstantProperties.getRegion(), request);
            log.info("Upload FileId = {}", response.getFileId());

            JSONObject resultMap = new JSONObject();

            resultMap.put("mediaFileId", response.getFileId());
            resultMap.put("mediaUrl", response.getMediaUrl());
            return resultMap;
        } catch (Exception e) {
            // 业务方进行异常处理
            log.error("Upload Err", e);
        }

        return null;


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo) throws TencentCloudSDKException {
        //保存接口，需要封装保存对象使用mapper进行保存。
        //是否可以根据meidaField字段查询到 media_duration ,media_file_id等，答案是可以


        MediaInfo mediaInfo = vodService.getMediaInfo(trackInfoVo);


        TrackInfo trackInfo = new TrackInfo();

        BeanUtils.copyProperties(trackInfoVo, trackInfo);

        trackInfo.setUserId(AuthContextHolder.getUserId() == null ? 1L : AuthContextHolder.getUserId());
        trackInfo.setMediaDuration(mediaInfo.getMetaData().getDuration());
        trackInfo.setMediaFileId(mediaInfo.getFileId());
        trackInfo.setMediaUrl(mediaInfo.getBasicInfo().getMediaUrl());
        trackInfo.setMediaSize(mediaInfo.getMetaData().getSize());
        trackInfo.setMediaType(mediaInfo.getBasicInfo().getType());
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);

        // 查询相同专辑中 order_num 的最大值
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId());
        queryWrapper.select(TrackInfo::getOrderNum);
        TrackInfo maxOrderTrack = this.getOne(queryWrapper.orderByDesc(TrackInfo::getOrderNum).last("LIMIT 1"));
        int saveOrderNum = (maxOrderTrack != null ? maxOrderTrack.getOrderNum() : 0) + 1;
        trackInfo.setOrderNum(saveOrderNum);
        trackInfoMapper.insert(trackInfo);

        LambdaUpdateWrapper<AlbumInfo> updateWrapper = new LambdaUpdateWrapper<AlbumInfo>().eq(AlbumInfo::getId, trackInfo.getAlbumId()).set(AlbumInfo::getIncludeTrackCount, saveOrderNum);
        albumInfoService.update(updateWrapper);


        ExecutorService threadPool = Executors.newFixedThreadPool(4);

        CompletableFuture.runAsync(() -> {
                    TrackStat trackStat = new TrackStat();
                    trackStat.setTrackId(trackInfo.getId());
                    trackStat.setStatType(SystemConstant.TRACK_STAT_PLAY);
                    trackStat.setStatNum(0);
                    trackStatMapper.insert(trackStat);
                }, threadPool)
                .runAsync(() -> {
                    TrackStat trackStat = new TrackStat();
                    trackStat.setTrackId(trackInfo.getId());
                    trackStat.setStatType(SystemConstant.TRACK_STAT_COLLECT);
                    trackStat.setStatNum(0);
                    trackStatMapper.insert(trackStat);
                }, threadPool)
                .runAsync(() -> {
                    TrackStat trackStat = new TrackStat();
                    trackStat.setTrackId(trackInfo.getId());
                    trackStat.setStatType(SystemConstant.TRACK_STAT_PRAISE);
                    trackStat.setStatNum(0);
                    trackStatMapper.insert(trackStat);
                }, threadPool)
                .runAsync(() -> {
                    TrackStat trackStat = new TrackStat();
                    trackStat.setTrackId(trackInfo.getId());
                    trackStat.setStatType(SystemConstant.TRACK_STAT_COMMENT);
                    trackStat.setStatNum(0);
                    trackStatMapper.insert(trackStat);
                }, threadPool);
    }
}
